package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.ActivityInfoMapper;
import com.atguigu.gmall.activity.mapper.ActivityRuleMapper;
import com.atguigu.gmall.activity.mapper.ActivitySkuMapper;
import com.atguigu.gmall.activity.mapper.CouponInfoMapper;
import com.atguigu.gmall.activity.service.ActivityInfoService;
import com.atguigu.gmall.activity.service.CouponInfoService;
import com.atguigu.gmall.model.activity.*;
import com.atguigu.gmall.model.cart.CarInfoVo;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.ActivityType;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ：Shine
 * @description：
 * @date ：2021/3/11 20:47
 */
@Service
public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, ActivityInfo> implements ActivityInfoService {

    @Autowired
    private ActivityInfoMapper activityInfoMapper;

    @Autowired
    private ActivityRuleMapper activityRuleMapper;

    @Autowired
    private ActivitySkuMapper activitySkuMapper;

    @Autowired
    private CouponInfoMapper couponInfoMapper;

    @Autowired
    private CouponInfoService couponInfoService;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Override
    public IPage<ActivityInfo> getPage(Page<ActivityInfo> pageParam) {
        QueryWrapper<ActivityInfo> activityInfoQueryWrapper = new QueryWrapper<>();
        activityInfoQueryWrapper.orderByDesc("id");
        IPage<ActivityInfo> activityInfoIPage = activityInfoMapper.selectPage(pageParam, activityInfoQueryWrapper);

        //给活动类型赋值
        activityInfoIPage.getRecords().stream().forEach((activityInfo -> {
            activityInfo.setActivityTypeString(ActivityType.getNameByType(activityInfo.getActivityType()));
        }));
        return activityInfoIPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveActivityRule(ActivityRuleVo activityRuleVo) {
        //先删除数据，在新增数据
        activitySkuMapper.delete(new QueryWrapper<ActivitySku>().eq("activity_id", activityRuleVo.getActivityId()));
        activityRuleMapper.delete(new QueryWrapper<ActivityRule>().eq("activity_id", activityRuleVo.getActivityId()));

        //获取到优惠券id列表集合,先将activity_id解除绑定再进行赋值,一定要根据活动id去查询，前端页面删除优惠券的时候将优惠券id也给移除了，不可以根据他去更新数据
        QueryWrapper<CouponInfo> couponInfoQueryWrapper = new QueryWrapper<>();
        couponInfoQueryWrapper.eq("activity_id", activityRuleVo.getActivityId());
        CouponInfo couponInfo1 = new CouponInfo();
        couponInfo1.setActivityId(0L);
        couponInfoMapper.update(couponInfo1, couponInfoQueryWrapper);

        List<ActivitySku> activitySkuList = activityRuleVo.getActivitySkuList();
        List<ActivityRule> activityRuleList = activityRuleVo.getActivityRuleList();
        for (ActivitySku activitySku : activitySkuList) {
            //需要将活动id赋值非当前对象
            activitySku.setActivityId(activityRuleVo.getActivityId());
            activitySkuMapper.insert(activitySku);
        }

        for (ActivityRule activityRule : activityRuleList) {
            activityRule.setActivityId(activityRuleVo.getActivityId());
            activityRuleMapper.insert(activityRule);
        }

        List<Long> couponIdList = activityRuleVo.getCouponIdList();
        if (!CollectionUtils.isEmpty(couponIdList)) {
            for (Long couponId : couponIdList) {
                CouponInfo couponInfo = couponInfoService.getById(couponId);
                couponInfo.setActivityId(activityRuleVo.getActivityId());
                couponInfoMapper.updateById(couponInfo);
            }
        }

    }

    @Override
    public List<SkuInfo> findSkuInfoByKeyword(String keyword) {
        List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoByKeyword(keyword);

        //将组成一个新的skuIdList集合
        List<Long> skuIdList = skuInfoList.stream().map(SkuInfo::getId).collect(Collectors.toList());

        //获取当前活动的skuId
        List<Long> existSkuIdList = activityInfoMapper.selectExistSkuIdList(skuIdList);

        //  通过skuId 获取到当前对象的集合
        List<Object> skuInfos = existSkuIdList.stream().map(skuId -> productFeignClient.getSkuInfo(skuId)).collect(Collectors.toList());

        //将已经添加活动的商品剔除
        skuInfoList.removeAll(skuInfos);
        return skuInfoList;
    }

    @Override
    public Map<String, Object> findActivityRuleList(Long id) {
        HashMap<String, Object> map = new HashMap<>();
        //获取活动规则
        List<ActivityRule> activityRuleList = activityRuleMapper.selectList(new QueryWrapper<ActivityRule>().eq("activity_id", id));
        map.put("activityRuleList", activityRuleList);

        //获取活动范围列表
        List<ActivitySku> activitySkuList = activitySkuMapper.selectList(new QueryWrapper<ActivitySku>().eq("activity_id", id));
        //将对象集合中的skuId取出组成一个新的List
        List<Long> skuIdList = activitySkuList.stream().map(ActivitySku::getSkuId).collect(Collectors.toList());
        List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoBySkuIdList(skuIdList);
        map.put("skuInfoList", skuInfoList);

        //将优惠券信息展示
        QueryWrapper<CouponInfo> couponInfoQueryWrapper = new QueryWrapper<>();
        couponInfoQueryWrapper.eq("activity_id", id);
        List<CouponInfo> couponInfoList = couponInfoMapper.selectList(couponInfoQueryWrapper);
        map.put("couponInfoList", couponInfoList);
        return map;

    }

    @Override
    public List<ActivityRule> findActivityRule(Long skuId) {
        List<ActivityRule> activityRuleList = activityInfoMapper.selectActivityRuleList(skuId);
        return activityRuleList;
    }

    @Override
    public List<CarInfoVo> findCartActivityRuleMap(List<CartInfo> cartInfoList, Map<Long, Long> skuIdToActivityIdMap) {
        List<CarInfoVo> carInfoVoList = new ArrayList<>();

        //定义一个map集合来存储skuId和cartInfo信息
        HashMap<Long, CartInfo> skuIdToCartInfoMap = new HashMap<>();
        for (CartInfo cartInfo : cartInfoList) {
            skuIdToCartInfoMap.put(cartInfo.getSkuId(), cartInfo);
        }

        //通过skuIdList找到对应的活动集合
        List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(skuIdList)) return new ArrayList<>();
        List<ActivityRule> activityRuleList = activityInfoMapper.selectCartActivityRuleList(skuIdList);

        //以skuId进行分组
        Map<Long, List<ActivityRule>> skuIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(ActivityRule::getSkuId));

        //以activityId进行分组
        Map<Long, List<ActivityRule>> activityIdToActivityRuleListAllMap = activityRuleList.stream().collect(Collectors.groupingBy(ActivityRule::getActivityId));
        Iterator<Map.Entry<Long, List<ActivityRule>>> iterator = activityIdToActivityRuleListAllMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<ActivityRule>> entry = iterator.next();
            Long activityId = entry.getKey();
            List<ActivityRule> currentActivityRuleList = entry.getValue();

            //    获取当前活动集合中的所有skuId，set方法自动去重，但是他没有下标，不可以使用get（0）来获取数据
            Set<Long> activitySkuIdSet = currentActivityRuleList.stream().map(ActivityRule::getSkuId).collect(Collectors.toSet());

            //创建一个cartInfoVO对象，来存储页面需要渲染的数据
            CarInfoVo carInfoVo = new CarInfoVo();
            List<CartInfo> currentCartInfoList = new ArrayList<>();
            //获取cartInfo信息
            for (Long skuId : activitySkuIdSet) {
                CartInfo cartInfo = skuIdToCartInfoMap.get(skuId);
                currentCartInfoList.add(cartInfo);
                //记录skuId和activityId
                skuIdToActivityIdMap.put(skuId, activityId);
            }
            carInfoVo.setCartInfoList(currentCartInfoList);

            //    根据skuId获取对应的活动列表
            List<ActivityRule> skuActivityRuleList = skuIdToActivityRuleListMap.get(activitySkuIdSet.iterator().next());
            carInfoVo.setActivityRuleList(skuActivityRuleList);
            carInfoVoList.add(carInfoVo);
        }

        return carInfoVoList;
    }

    @Override
    public Map<Long, ActivityRule> findTradeActivityRuleMap(List<OrderDetail> orderDetailList) {
        //购物项activityId对应的最优活动规则
        Map<Long, ActivityRule> activityIdToActivityRuleMap = new HashMap<>();

        //获取skuId对应的购物项
        Map<Long, OrderDetail> skuIdToOrderDetailMap = new HashMap<>();
        for(OrderDetail orderDetail : orderDetailList) {
            skuIdToOrderDetailMap.put(orderDetail.getSkuId(), orderDetail);
        }
        //  获取skuId 列表
        List<Long> skuIdList = orderDetailList.stream().map(OrderDetail::getSkuId).collect(Collectors.toList());
        //  查询skuId 对应的活动规则
        List<ActivityRule> activityRuleList = activityInfoMapper.selectCartActivityRuleList(skuIdList);
        //skuId分组，获取skuId对应的活动规则
        Map<Long, List<ActivityRule>> skuIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getSkuId()));
        //活动Id分组，获取活动Id对应的sku
        Map<Long, List<ActivityRule>> activityIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(activityRule -> activityRule.getActivityId()));

        Iterator<Map.Entry<Long, List<ActivityRule>>> iterator = activityIdToActivityRuleListMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<ActivityRule>> entry = iterator.next();
            //  Long activityId = entry.getKey();
            List<ActivityRule> currentActivityRuleList = entry.getValue();
            // 活动id对应的购物车skuId列表。
            Set<Long> activitySkuIdSet = currentActivityRuleList.stream().map(ActivityRule::getSkuId).collect(Collectors.toSet());
            // 该活动的总金额 {如果是满减打折则使用activityTotalAmount}
            BigDecimal activityTotalAmount = new BigDecimal("0");
            // 该活动订单明细的个数{如果是满件打折的时候，需要判断activityTotalNum}
            Integer activityTotalNum = 0;
            for (Long skuId : activitySkuIdSet) {
                //  获取当前sku对应的活动id
                OrderDetail orderDetail = skuIdToOrderDetailMap.get(skuId);
                //  订单明细的总金额
                BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                //  计算这个活动的总金额
                activityTotalAmount = activityTotalAmount.add(skuTotalAmount);
                activityTotalNum += orderDetail.getSkuNum();

            }
            // 获取skuId 对应的该活动规则
            Long skuId = activitySkuIdSet.iterator().next();
            List<ActivityRule> skuActivityRuleList = skuIdToActivityRuleListMap.get(skuId);
            for (ActivityRule activityRule : skuActivityRuleList) {
                //  数据库存储的 FULL_REDUCTION
                if (activityRule.getActivityType().equals(ActivityType.FULL_REDUCTION.name())) {
                    //  活动总金额大于活动规则的总金额
                    if (activityTotalAmount.compareTo(activityRule.getConditionAmount()) > -1) {
                        //  设置优惠后见减少的金额
                        activityRule.setReduceAmount(activityRule.getBenefitAmount());
                        //  设置好skuId 列表
                        activityRule.setSkuIdList(new ArrayList<>(activitySkuIdSet));
                        //  活动Id对应的最优规则
                        activityIdToActivityRuleMap.put(activityRule.getActivityId(), activityRule);
                        break;
                    }
                } else {
                    //  如果订单项购买个数大于等于满减件数，则优化打折 FULL_DISCOUNT
                    if (activityTotalNum.intValue() >= activityRule.getConditionNum()) {
                        //  9折  9/10 = 0.9  totalAmount *0.9
                        BigDecimal skuDiscountTotalAmount = activityTotalAmount.multiply(activityRule.getBenefitDiscount().divide(new BigDecimal("10")));
                        //  activityTotalAmount-skuDiscountTotalAmount
                        BigDecimal reduceAmount = activityTotalAmount.subtract(skuDiscountTotalAmount);
                        //  设置优惠后的金额reduceAmount
                        activityRule.setReduceAmount(reduceAmount);
                        activityRule.setSkuIdList(new ArrayList<>(activitySkuIdSet));
                        activityIdToActivityRuleMap.put(activityRule.getActivityId(), activityRule);
                        break;
                    }
                }
            }
        }
        return activityIdToActivityRuleMap;


    }

}
